﻿//
// Copyright (c) 2024 BPer
//
#include <bperrtp/BPerRtpFUAPayload2.h>
#include <bperrtp/BPerRtpConstant.h>

#include <bperutil/BPerAvType.h>
#include <bperutil/sys/BPerLog.h>


int32_t bPer_decode_h264_fua2(BPerBuffer* buf,Fua2H264DataCache* pkt){
	if (!bPer_buffer_require(buf,2)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2);
		}
		// FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8
		uint8_t v = bPer_read_1bytes(buf);
		pkt->nri = (BPerAvcNaluType)(v & (~kNalTypeMask));

		// FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8
		v = bPer_read_1bytes(buf);
		pkt->start = v & kStart;
		pkt->end = v & kEnd;
		pkt->nalu_type = (BPerAvcNaluType)(v & kNalTypeMask);
		if (!bPer_buffer_require(buf,1)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
		}

		return BPer_Ok;
}

int32_t bPer_encode_h264_fua2(BPerBuffer* buf,BPerFua2H264Data* pkt){
	if (!bPer_buffer_require(buf,2 + pkt->nb)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + pkt->nb);
		}
		char *p = buf->head;

		uint8_t fu_indicate = kFuA;
		fu_indicate |= (pkt->nri & (~kNalTypeMask));
		*p++ = fu_indicate;

		// FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8
		uint8_t fu_header = pkt->nalu_type;
		if (pkt->start) {
			fu_header |= kStart;
		}
		if (pkt->end) {
			fu_header |= kEnd;
		}
		*p++ = fu_header;

		// FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8
		bPer_memcpy(p, pkt->payload, pkt->nb);

		// Consume bytes.
		bPer_buffer_skip(buf,2 + pkt->nb);

		return BPer_Ok;
}
int32_t bPer_decode_h265_fua2(BPerBuffer* buf,Fua2H265DataCache* pkt){
	if (!bPer_buffer_require(buf,3)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER, "decode_h265_fua2 requires %d bytes", 3);
		}
		// FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8
		uint8_t v = bPer_read_1bytes(buf);
        pkt->nri =  (BPerHevcNaluType)((v>>1) & 0x3f);
		v=bPer_read_1bytes(buf);
		// FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8
		v = bPer_read_1bytes(buf);
		pkt->start = v & kStart;
		pkt->end = v & kEnd;
		pkt->nalu_type = (BPerHevcNaluType)(v & 0x3F);
		if (!bPer_buffer_require(buf,1)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER, "decode_h265_fua2 requires %d bytes", 1);
		}

		return BPer_Ok;
}
int32_t bPer_encode_h265_fua2(BPerBuffer* buf,BPerFua2H265Data* pkt){
	if (!bPer_buffer_require(buf,3 + pkt->nb)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3 + pkt->nb);
		}
	// FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8
		char *p = buf->head;
		*p++=H265_kFuA<<1;//49<<1;
		*p++=1;
		uint8_t fu_header = pkt->nalu_type;
		if (pkt->start) {
			fu_header |= kStart;
		}
		if (pkt->end) {
			fu_header |= kEnd;
		}
		*p++ = fu_header;

		// FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8
		bPer_memcpy(p, pkt->payload, pkt->nb);

		// Consume bytes.
		bPer_buffer_skip(buf,3 + pkt->nb);

		return BPer_Ok;
}
